/* Copyright (c) 2010, David Kreuter. See LICENSE for more information */

#ifndef IN_HEADERS_H
#error This file should be included through "headers.h"
#endif

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#ifdef _WIN32
	#include <windows.h>
	#undef ERROR
	#define FOREGROUND_WHITE \
		( FOREGROUND_RED   | \
		  FOREGROUND_GREEN | \
		  FOREGROUND_BLUE  )
	#define Co(c) FOREGROUND_##c // Co(INTENSITY) ;)
	#define S(z) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),z);
#endif

typedef unsigned int   uint32;
typedef unsigned short uint16;
typedef unsigned char  uint8;

typedef int   sint32;
typedef short sint16;
typedef char  sint8;

int  read_file(char *, uint8 **, uint32 *);
int write_file(char *, uint8 **, uint32 *);
void nop(char *s, ...);
void hexdump(uint8*, uint32, char*);
extern uint32 ident;

#define L {uint8 a=ident;printf("#%4d %15s: ",__LINE__,__FILE__);\
	while(a--)printf("    ");}

#ifdef _WIN32
	#define ERROR L S(Co(RED));printf("ERROR ");S(Co(WHITE));printf
	#define DEBUG L printf
#else
	#define ERROR L printf("\x1B[31mERROR \x1B[0m");printf
	#define DEBUG L printf
#endif
//#define DEBUG nop

#define START(name)      DEBUG(#name"\n");ident++
#define END(name,retval) ident--; return (retval); name##_error: ident--;
#define ENDV(name)       ident--; return         ; name##_error: ident--;

#define MAGIC(pos,sig,name) if(RL(pos)!=sig)\
	{ERROR("No magic '"#sig"' at %8d (%8x)\n",(uint32)pos,RL(pos));\
	goto name##_error;}
#define CHECK_LEN(p,name) if(RL(p)!=len)\
        {ERROR("Wrong lenght (File: %8d Header: %8d)\n",RL(p),len);\
	goto name##_error;}
#define READ_NAME(to,from) {memcpy(to, from, 16); to[16]=0;}
#define INIT_OFF_GENERAL(pref,p,type,o,t) pref##_##type *t=p->type+i; \
	/*hexdump(buf+type##_offset+16+i*4,4,#pref"_"#type"-index-bytes");*/ \
	t->offset=o##_offset+RL(type##_offset+16+(p->num_##type##s+i)*4);
#define INIT_OFF_NO_NAME(pref,p,type,o,t) INIT_OFF_GENERAL(pref,p,type,o,t)\
	DEBUG("%d. "#type" offset: %8x\n",i,t->offset);
#define INIT_OFF_AND_NAME(pref,p,type,o,t) INIT_OFF_GENERAL(pref,p,type,o,t) \
	READ_NAME(t->name, buf+(type##_offset+16+p->num_##type##s*8+i*16)); \
	DEBUG("%d. "#pref"_"#type" offset: %8x '%s\'\n",i,t->offset,t->name);
#define FREE_LOOP(a,n,f) if(a->n){ \
	for(uint32 i=0;i<a->num_##n##s;i++)f(a->n+i);free(a->n);}

#define RL(p) (*(uint32*)(buf+(p)))
#define RS(p) (*(uint16*)(buf+(p)))
#define recalloc(a,b,c) realloc(a,(b)*(c))
#define countof(a) (sizeof((a))/sizeof((a)[0]))

#define NARC 0x4352414e
#define BTAF 0x46415442
#define BTNF 0x464e5442
#define GMIF 0x46494d47
#define BMD0 0x30444d42
#define MDL0 0x304c444d
#define BTX0 0x30585442
#define TEX0 0x30584554
